/*
 * @Author: crissu 13750782397@163.com
 * @Date: 2024-05-22 01:41:14
 * @LastEditors: crissu 13750782397@163.com
 * @LastEditTime: 2024-05-26 23:37:00
 * @FilePath: /try_concurrence/anytest/anytest.go
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
package anytest

import (
	"fmt"
	"sync"
	"time"
	"try_concurrence/gsema"
)

// 讨论话题：控制同时并发的数量
// https://eddycjy.gitbook.io/golang/di-1-ke-za-tan/control-goroutine

var wg = sync.WaitGroup{}

func ControlGroutineNumsByChan() {
	userCount := 10
	ch := make(chan bool, 2)
	for i := 0; i < userCount; i++ {
		ch <- true
		go readUseChan(ch, i)
	}
	time.Sleep(10 * time.Second)
}

func readUseChan(ch chan bool, i int) {
	time.Sleep(1 * time.Second)
	fmt.Printf("go func: %d, time:%v\n", i, time.Now().UnixMilli())
	<-ch
}

func ControlGroutineNumsBySync() {
	userCount := 10
	for i := 0; i < userCount; i++ {
		wg.Add(1)
		go readUseWg(i)
	}

	wg.Wait()
}

func readUseWg(i int) {
	defer wg.Done()
	time.Sleep(1 * time.Second)
	fmt.Printf("go func: %d, time:%v\n", i, time.Now().UnixMilli())
}

func ControlGroutineNumsBySyncAndChan() {
	userCount := 10
	ch := make(chan bool, 2)
	for i := 0; i < userCount; i++ {
		wg.Add(1)
		go readUseWgAndChan(ch, i)
	}

	wg.Wait()
}

func readUseWgAndChan(ch chan bool, i int) {
	defer wg.Done()

	ch <- true
	fmt.Printf("go func: %d, time: %d\n", i, time.Now().Unix())
	time.Sleep(time.Second)
	<-ch
}

func ControlGroutineNumsBySyncAndChan2() {
	userCount := 10
	ch := make(chan bool, 2)
	for i := 0; i < userCount; i++ {
		wg.Add(1)
		ch <- true
		go readUseWgAndChan2(ch, i)
	}

	wg.Wait()
}

func readUseWgAndChan2(ch chan bool, i int) {
	defer wg.Done()
	fmt.Printf("go func: %d, time: %d\n", i, time.Now().Unix())
	time.Sleep(time.Second)
	<-ch
}

var sema = gsema.NewSemaphore(3)

func ControlGroutineNumsByGsema() {
	userCount := 10
	for i := 0; i < userCount; i++ {
		go readUseGsema(i)
	}

	sema.Wait()
}

func readUseGsema(i int) {
	defer sema.Done()
	sema.Add(1)
	fmt.Printf("go func: %d, time: %d\n", i, time.Now().Unix())
	time.Sleep(time.Second)
}

func ControlGroutineNumsByGsema2() {
	userCount := 10
	for i := 0; i < userCount; i++ {
		sema.Add(1)
		go readUseGsema2(i)
	}

	sema.Wait()
}

func readUseGsema2(i int) {
	defer sema.Done()
	fmt.Printf("go func: %d, time: %d\n", i, time.Now().Unix())
	time.Sleep(time.Second)
}

func ControlGroutineNumsBySmart() {
	userCount := 10
	ch := make(chan int, 5)
	for i := 0; i < userCount; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for d := range ch {
				fmt.Printf("go func: %d, time: %d\n", d, time.Now().Unix())
				time.Sleep(time.Second * time.Duration(d))
			}
		}()
	}

	for i := 0; i < 10; i++ {
		ch <- 1
		ch <- 2
		time.Sleep(time.Second)
	}

	close(ch)
	wg.Wait()
}
